﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace UPARKTaskManager
{
    class Program
    {
        static string TaskPath =Environment.CurrentDirectory+ @"\Tasks";
        static string SocketServerIP = "192.168.1.100";
        static int SocketServerPort = 8888;
        static void Main(string[] args) 
        {
            AllTasks.GetInstance().GetAllTask(TaskPath);
            Console.WriteLine("Load All Task Completely");
            IPEndPoint ServerIPE = new IPEndPoint(IPAddress.Parse(SocketServerIP), SocketServerPort);
            Socket sSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            sSocket.Bind(ServerIPE);
            sSocket.Listen(10);
            bool started = true;
            while (started)
            {
                Socket eachSocket = sSocket.Accept();
                ClientThread newClient = new ClientThread(eachSocket);
                Console.WriteLine("A Client Has Connected!");
                Thread newThread = new Thread(new ThreadStart(newClient.ClientService));
                newThread.Start();
            }
        }

        public class ClientThread
        {
            private bool beConnected = false;
            private Socket socket = null;


            public ClientThread(Socket clientSocket)
            {
                this.socket = clientSocket;
                this.beConnected = true;
            }

            public void ClientService()
            {
                while (this.beConnected)
                {
                    string infoType = GetInfoType();
                    if (infoType == "AnyDetectTask")
                    {
                        Console.WriteLine("<<<<<<<<<<<<<<GET AnyDetectTask Info");
                        if (AllTasks.GetInstance().DetectTaskQueue.Count == 0)
                        {
                            SendInfo("NoDetectTask");
                            Console.WriteLine(">>>>>>>>>>>>Send NoDetectTask Info");
                        }
                        else
                        {
                            SendInfo("NewDetectTask");
                            Console.WriteLine(">>>>>>>>>>>>>Send NewDetectTask Info");
                            string filePath = AllTasks.GetInstance().DetectTaskQueue.Dequeue();
                            if (!SendFile(filePath))
                            {
                                Console.WriteLine("**************Send NewDetectTask Failed");
                                AllTasks.GetInstance().DetectTaskQueue.Enqueue(filePath);
                            }
                            else
                            {
                                //发送成功删除该任务文件
                                // File.Delete(filePath);
                            }
                        }
                    }
                    else if (infoType == "DetectedTask")
                    {
                        string filePath = string.Format("{0}/SurveyTasks/{1}.zip", TaskPath, Guid.NewGuid().ToString());
                        if (ReceiveFile(filePath))
                        {
                            AllTasks.GetInstance().SurveyTaskQueue.Enqueue(filePath);
                        }
                    }
                    else if (infoType == "AnyCatchSVTask")
                    {
                        Console.WriteLine(">>>>>>>>>>>>GET AnyCatchSVTask Info");
                        if (AllTasks.GetInstance().CatchSVTaskQueue.Count == 0)
                        {
                            SendInfo("NoCatchSVTask");
                            Console.WriteLine(">>>>>>>>>>>>Send NoCatchSVTask Info");
                        }
                        else
                        {
                            SendInfo("NewCatchSVTask");
                            Console.WriteLine(">>>>>>>>>>>>>Send NewCatchSVTask Info");
                            string filePath = AllTasks.GetInstance().CatchSVTaskQueue.Dequeue();
                            if (!SendFile(filePath))
                            {
                                Console.WriteLine("**************Send NewCatchSVTask Failed");
                                AllTasks.GetInstance().CatchSVTaskQueue.Enqueue(filePath);
                            }
                            else
                            {
                                //发送成功删除该任务文件
                                // File.Delete(filePath);
                            }
                        }

                    }
                    else if (infoType == "CatchedSVTask")
                    {
                        string filePath = string.Format("{0}/DetectTasks/{1}.zip", TaskPath, Guid.NewGuid().ToString());
                        if (ReceiveFile(filePath))
                        {
                            AllTasks.GetInstance().DetectTaskQueue.Enqueue(filePath);
                        }
                    }
                    else if (infoType == "AnySurveyTask")
                    {
                        Console.WriteLine(">>>>>>>>>>>>GET AnySurveyTask Info");
                        if (AllTasks.GetInstance().SurveyTaskQueue.Count == 0)
                        {
                            SendInfo("NoSurveyTask");
                            Console.WriteLine(">>>>>>>>>>>>Send NoSurveyTask Info");
                        }
                        else
                        {
                            SendInfo("NewSurveyTask");
                            Console.WriteLine(">>>>>>>>>>>>>Send NewSurveyTask Info");
                            string filePath = AllTasks.GetInstance().SurveyTaskQueue.Dequeue();
                            if (!SendFile(filePath))
                            {
                                Console.WriteLine("**************Send NewSurveyTask Failed");
                                AllTasks.GetInstance().SurveyTaskQueue.Enqueue(filePath);
                            }
                            else
                            {
                                //发送成功删除该任务文件
                                // File.Delete(filePath);
                            }
                        }
                    }

                }
            }

            public string GetInfoType()
            {
                string infoType = "";
                byte[] getBytes = new byte[1024];
                try
                {
                	int index = this.socket.Receive(getBytes);
                    infoType = Encoding.Default.GetString(getBytes, 0, index);
                }
                catch (System.Exception ex)
                {
                    //Console.WriteLine("A Connect Closed");
                    return null;
                }
                return infoType;
            }

            public void SendInfo(string info)
            {
                byte[] sendBytes = new byte[1024];
                sendBytes = Encoding.ASCII.GetBytes(info);
                socket.Send(sendBytes, sendBytes.Length, SocketFlags.None);
            }

            public bool SendFile(string filePath)
            {
                Console.WriteLine("===============Start Send File");
                FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read);
                long fileLeftLength = fs.Length;
                byte[] sendBytes = new byte[1024];
                sendBytes = Encoding.ASCII.GetBytes(fileLeftLength.ToString());
                int lenIndex = 0;
                try
                {
                	 lenIndex=socket.Send(sendBytes);
                }
                catch (System.Exception ex)
                {
                    fs.Close();
                    return false;
                }

                if (lenIndex < 1024)
                {
                    byte[] nullBytes = new byte[1024 - lenIndex];
                    try
                    {
                    	socket.Send(nullBytes);
                    }
                    catch (System.Exception ex)
                    {
                        fs.Close();
                        return false;
                    }
                }
                sendBytes = new byte[1024];
                while(fileLeftLength>0)
                {
                    int index=fs.Read(sendBytes, 0, sendBytes.Length);
                    try
                    {
                    	socket.Send(sendBytes,0,index,SocketFlags.None);
                    }
                    catch (System.Exception ex)
                    {
                        fs.Close();
                        return false;
                    }
                    fileLeftLength -= index;
                }
                fs.Close();
                Console.WriteLine("===============Finish Send File");
                return true;
            }

            public bool ReceiveFile(string filePath)
            {

                FileStream fs = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.ReadWrite);
                BinaryWriter bw = new BinaryWriter(fs);

                int index = 0;
                byte[] receiveBytes = new byte[1024];
                Console.WriteLine("===============Start Received File");
               
                //先接收文件长度信息
                try
                {
                    index = socket.Receive(receiveBytes);
                }
                catch (System.Exception ex)
                {
                    Console.WriteLine("A Connect Closed");
                    Console.WriteLine("*******************Failed Received File");
                    return false;
                }
                string lengthStr = Encoding.Default.GetString(receiveBytes);
                int fileLeftLength = Convert.ToInt32(lengthStr);
                Console.WriteLine("############This file's length is " + fileLeftLength);
              
                while (fileLeftLength > 0)
                {
                   try
                    {
	                     index = socket.Receive(receiveBytes);
                    }
                    catch (System.Exception ex)
                    {
                        Console.WriteLine("A Connect Closed");
                        Console.WriteLine("*******************Failed Received File");
                        bw.Close();
                        fs.Close();
                        return false;
                    }
                    bw.Write(receiveBytes, 0, index);
                    fileLeftLength -= index;
                }
                Console.WriteLine("===============Finish Received File");
                bw.Close();
                fs.Close();
                return true;
            }
        }

    }
}
